package com.governtalk.backend.service.impl;

import com.governtalk.backend.dto.resource.LearningResourceDto;
import com.governtalk.backend.entity.LearningResource;
import com.governtalk.backend.entity.User;
import com.governtalk.backend.repository.LearningResourceRepository;
import com.governtalk.backend.service.ResourceService;
import com.governtalk.backend.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.Collections;

@Service
public class ResourceServiceImpl implements ResourceService {
    
    @Autowired
    private LearningResourceRepository resourceRepository;
    
    @Autowired
    private UserService userService;
    
    private static final String UPLOAD_DIR = "uploads/resources/";
    
    @Override
    public Page<LearningResourceDto> searchResources(String keyword, String type, Long categoryId, 
                                                    String sortBy, String sortOrder, Pageable pageable) {
        Page<LearningResource> resources;
        
        if (keyword != null && !keyword.isEmpty()) {
            resources = resourceRepository.findByTitleContainingIgnoreCaseAndIsPublicTrue(keyword, pageable);
        } else if (categoryId != null) {
            resources = resourceRepository.findByCategoryIdAndIsPublicTrue(categoryId, pageable);
        } else {
            resources = resourceRepository.findByIsPublicTrueAndStatus(LearningResource.ResourceStatus.APPROVED, pageable);
        }
        
        return resources.map(this::convertToDto);
    }
    
    @Override
    public List<LearningResourceDto> getHotResources(int count) {
        Pageable pageable = PageRequest.of(0, count);
        List<LearningResource> resources = resourceRepository.findHotResources(pageable);
        return resources.stream().map(this::convertToDto).collect(Collectors.toList());
    }
    
    @Override
    public List<LearningResourceDto> getNewResources(int count) {
        Pageable pageable = PageRequest.of(0, count);
        List<LearningResource> resources = resourceRepository.findNewResources(pageable);
        return resources.stream().map(this::convertToDto).collect(Collectors.toList());
    }
    
    @Override
    public LearningResourceDto getResourceDetail(Long resourceId) {
        LearningResource resource = resourceRepository.findById(resourceId)
                .orElseThrow(() -> new RuntimeException("Resource not found"));
        
        // 增加浏览次数
        resource.setViewCount(resource.getViewCount() + 1);
        resourceRepository.save(resource);
        
        return convertToDto(resource);
    }
    
    @Override
    public LearningResourceDto uploadResource(MultipartFile file, String title, String description, 
                                            String type, Long categoryId) {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String username = authentication.getName();
            User user = userService.findByUsername(username);
            
            String fileName = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
            Path filePath = Paths.get(UPLOAD_DIR + fileName);
            
            Files.createDirectories(filePath.getParent());
            Files.write(filePath, file.getBytes());
            
            LearningResource resource = LearningResource.builder()
                    .title(title)
                    .description(description)
                    .fileType(file.getContentType())
                    .fileSize(file.getSize())
                    .filePath("/uploads/resources/" + fileName)
                    .fileUrl("/api/resources/" + fileName + "/download")
                    .user(user)
                    .categoryId(categoryId)
                    .isPublic(true)
                    .status(LearningResource.ResourceStatus.PENDING)
                    .downloadCount(0)
                    .viewCount(0)
                    .ratingCount(0)
                    .build();
            
            LearningResource savedResource = resourceRepository.save(resource);
            return convertToDto(savedResource);
            
        } catch (IOException e) {
            throw new RuntimeException("Failed to upload resource", e);
        }
    }
    
    @Override
    public String downloadResource(Long resourceId) {
        LearningResource resource = resourceRepository.findById(resourceId)
                .orElseThrow(() -> new RuntimeException("Resource not found"));
        
        // 增加下载次数
        resource.setDownloadCount(resource.getDownloadCount() + 1);
        resourceRepository.save(resource);
        
        return resource.getFileUrl();
    }
    
    @Override
    public void favoriteResource(Long resourceId) {
        // 这里需要实现收藏逻辑，可能需要创建收藏表
        // 暂时简化处理
    }
    
    @Override
    public Page<LearningResourceDto> getFavoriteResources(Pageable pageable) {
        // 这里需要实现获取收藏资源逻辑
        return Page.empty();
    }
    
    @Override
    public Page<LearningResourceDto> getResourceReviews(Long resourceId, Pageable pageable) {
        // 这里需要实现获取资源评论逻辑
        return Page.empty();
    }
    
    @Override
    public void addResourceReview(Long resourceId, Integer rating, String content) {
        // 这里需要实现添加资源评论逻辑
    }
    
    @Override
    public void approveResource(Long resourceId, Boolean approved, String reason) {
        LearningResource resource = resourceRepository.findById(resourceId)
                .orElseThrow(() -> new RuntimeException("Resource not found"));
        
        resource.setStatus(approved ? LearningResource.ResourceStatus.APPROVED : LearningResource.ResourceStatus.REJECTED);
        resource.setUpdatedAt(LocalDateTime.now());
        resourceRepository.save(resource);
    }
    
    @Override
    public void deleteResource(Long resourceId) {
        resourceRepository.deleteById(resourceId);
    }
    
    @Override
    public List<LearningResourceDto> getResourceCategories() {
        // 这里需要实现获取资源分类逻辑
        return Collections.emptyList();
    }
    
    private LearningResourceDto convertToDto(LearningResource resource) {
        return LearningResourceDto.builder()
                .id(resource.getId())
                .title(resource.getTitle())
                .description(resource.getDescription())
                .type(resource.getFileType())
                .status(resource.getStatus().name())
                .uploaderId(resource.getUser().getId())
                .uploaderName(resource.getUser().getUsername())
                .uploaderAvatar(resource.getUser().getAvatarUrl())
                .filePath(resource.getFilePath())
                .fileUrl(resource.getFileUrl())
                .thumbnailUrl(resource.getThumbnailUrl())
                .fileType(resource.getFileType())
                .fileSize(resource.getFileSize())
                .downloadCount(resource.getDownloadCount())
                .viewCount(resource.getViewCount())
                .rating(resource.getAverageRating())
                .ratingCount(resource.getRatingCount())
                .isFeatured(resource.getIsRecommended())
                .isHot(resource.getIsRecommended())
                .isRecommended(resource.getIsRecommended())
                .categoryId(resource.getCategoryId())
                .createdAt(resource.getCreatedAt())
                .updatedAt(resource.getUpdatedAt())
                .build();
    }
}
